Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / LXST.git / files / LXST / Codecs / libs / pyogg / opus_encoder.py

Displaying Raw • Download


LXST/Codecs/libs/pyogg/opus_encoder.py c74d2dd5cbffdff82fdb707ef50ce04937c9689f (c74d2dd5) Text, 13.59 KB

Tff7b72import T7ee787ctypes
Tff7b72from T7ee787typing Tff7b72import Te6edf3OptionalTb4b4b4, Te6edf3UnionTb4b4b4, Te6edf3ByteString

Tff7b72from T7ee787. Tff7b72import Te6edf3opus
Tff7b72from T7ee787.T7ee787pyogg_error Tff7b72import Te6edf3PyOggError

Tff7b72class T56d364OpusEncoderTb4b4b4:
T8b949e"""Encodes PCM data into Opus frames."""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_encoderTb4b4b4: Te6edf3OptionalTb4b4b4[Te6edf3ctypesTff7b72.Td2a8ffpointerTb4b4b4] Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_channelsTb4b4b4: Te6edf3OptionalTb4b4b4[Tffa657intTb4b4b4] Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_samples_per_secondTb4b4b4: Te6edf3OptionalTb4b4b4[Tffa657intTb4b4b4] Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_applicationTb4b4b4: Te6edf3OptionalTb4b4b4[Tffa657intTb4b4b4] Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_max_bytes_per_frameTb4b4b4: Te6edf3OptionalTb4b4b4[Te6edf3opusTff7b72.Td2a8ffopus_int32Tb4b4b4] Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_output_bufferTb4b4b4: Te6edf3OptionalTb4b4b4[Te6edf3ctypesTff7b72.Td2a8ffArrayTb4b4b4] Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_output_buffer_ptrTb4b4b4: Te6edf3OptionalTb4b4b4[Te6edf3ctypesTff7b72.Td2a8ffpointerTb4b4b4] Tff7b72= Tff7b72None

T8b949e# An output buffer of 4,000 bytes is recommended in
T8b949e# https://opus-codec.org/docs/opus_api-1.3.1/group__opus__encoder.html
Tff7b72selfTff7b72.Td2a8ffset_max_bytes_per_frameTb4b4b4(T79c0ff4000Tb4b4b4)

T8b949e#
T8b949e# User visible methods
T8b949e#

Tff7b72def Td2a8ffset_channelsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nTb4b4b4: Tffa657intTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Set the number of channels.

n must be either 1 or 2.

"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_encoder Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3n Tff7b72< T79c0ff0 Tff7b72or Te6edf3n Tff7b72> T79c0ff2Tb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffInvalid number of channels in call to Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffset_channels()Ta5d6ff"
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_channels Tff7b72= Te6edf3n
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffCannot change the number of channels after Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffthe encoder was created. Perhaps Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffset_channels() was called after encode()?Ta5d6ff"
Tb4b4b4)

Tff7b72def Td2a8ffset_sampling_frequencyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3samples_per_secondTb4b4b4: Tffa657intTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Set the number of samples (per channel) per second.

This must be one of 8000, 12000, 16000, 24000, or 48000.

Regardless of the sampling rate and number of channels
selected, the Opus encoder can switch to a lower audio
bandwidth or number of channels if the bitrate selected is
too low. This also means that it is safe to always use 48
kHz stereo input and let the encoder optimize the
encoding.

"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_encoder Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3samples_per_second Tff7b72in Tb4b4b4[T79c0ff8000Tb4b4b4, T79c0ff12000Tb4b4b4, T79c0ff16000Tb4b4b4, T79c0ff24000Tb4b4b4, T79c0ff48000Tb4b4b4]Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_samples_per_second Tff7b72= Te6edf3samples_per_second
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffSpecified sampling frequency Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ff(Tffd700{:d}Ta5d6ff) Ta5d6ff"Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3samples_per_secondTb4b4b4)Tff7b72+
Ta5d6ff"Ta5d6ffwas not one of the accepted valuesTa5d6ff"
Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffCannot change the sampling frequency after Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffthe encoder was created. Perhaps Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffset_sampling_frequency() was called after encode()?Ta5d6ff"
Tb4b4b4)

Tff7b72def Td2a8ffset_applicationTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3applicationTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Set the encoding mode.

This must be one of 'voip', 'audio', or 'restricted_lowdelay'.

'voip': Gives best quality at a given bitrate for voice
signals. It enhances the input signal by high-pass
filtering and emphasizing formants and
harmonics. Optionally it includes in-band forward error
correction to protect against packet loss. Use this mode
for typical VoIP applications. Because of the enhancement,
even at high bitrates the output may sound different from
the input.

'audio': Gives best quality at a given bitrate for most
non-voice signals like music. Use this mode for music and
mixed (music/voice) content, broadcast, and applications
requiring less than 15 ms of coding delay.

'restricted_lowdelay': configures low-delay mode that
disables the speech-optimized mode in exchange for
slightly reduced delay. This mode can only be set on an
newly initialized encoder because it changes the codec
delay.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_encoder Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffCannot change the application after Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffthe encoder was created. Perhaps Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffset_application() was called after encode()?Ta5d6ff"
Tb4b4b4)
Tff7b72if Te6edf3application Tff7b72== Ta5d6ff"Ta5d6ffvoipTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_application Tff7b72= Te6edf3opusTff7b72.Td2a8ffOPUS_APPLICATION_VOIP
Tff7b72elif Te6edf3application Tff7b72== Ta5d6ff"Ta5d6ffaudioTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_application Tff7b72= Te6edf3opusTff7b72.Td2a8ffOPUS_APPLICATION_AUDIO
Tff7b72elif Te6edf3application Tff7b72== Ta5d6ff"Ta5d6ffrestricted_lowdelayTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_application Tff7b72= Te6edf3opusTff7b72.Td2a8ffOPUS_APPLICATION_RESTRICTED_LOWDELAY
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffThe application specification Ta5d6ff'Tffd700{:s}Ta5d6ff'Ta5d6ff Ta5d6ff"Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3applicationTb4b4b4)Tff7b72+
Ta5d6ff"Ta5d6ffwasnTa5d6ff'Ta5d6fft one of the accepted values.Ta5d6ff"
Tb4b4b4)

Tff7b72def Td2a8ffset_max_bytes_per_frameTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3max_bytesTb4b4b4: Tffa657intTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Set the maximum number of bytes in an encoded frame.

Size of the output payload. This may be used to impose an
upper limit on the instant bitrate, but should not be used
as the only bitrate control.

TODO: Use OPUS_SET_BITRATE to control the bitrate.

"""
Tff7b72selfTff7b72.Td2a8ff_max_bytes_per_frame Tff7b72= Te6edf3opusTff7b72.Td2a8ffopus_int32Tb4b4b4(Te6edf3max_bytesTb4b4b4)
Te6edf3OutputBuffer Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffc_ubyte Tff7b72* Te6edf3max_bytes
Tff7b72selfTff7b72.Td2a8ff_output_buffer Tff7b72= Te6edf3OutputBufferTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_output_buffer_ptr Tff7b72= Tb4b4b4(
Te6edf3ctypesTff7b72.Td2a8ffcastTb4b4b4(Te6edf3ctypesTff7b72.Td2a8ffpointerTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_output_bufferTb4b4b4)Tb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffPOINTERTb4b4b4(Te6edf3ctypesTff7b72.Td2a8ffc_ubyteTb4b4b4)Tb4b4b4)
Tb4b4b4)
Tff7b72def Td2a8ffencodeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pcmTb4b4b4: Te6edf3UnionTb4b4b4[Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4, Tffa657memoryviewTb4b4b4]Tb4b4b4) Tff7b72-Tff7b72> Tffa657memoryviewTb4b4b4:
T8b949e"""Encodes PCM data into an Opus frame.

`pcm` must be formatted as bytes-like, with each sample taking
two bytes (signed 16-bit integers; interleaved left, then
right channels if in stereo).

If `pcm` is not writeable, a copy of the array will be made.

"""
T8b949e# If we haven't already created an encoder, do so now
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_encoder Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_encoder Tff7b72= Tff7b72selfTff7b72.Td2a8ff_create_encoderTb4b4b4(Tb4b4b4)
T8b949e# Sanity checks also satisfy mypy type checking
Tff7b72assert Tff7b72selfTff7b72.Td2a8ff_channels Tff7b72is Tff7b72not Tff7b72None
Tff7b72assert Tff7b72selfTff7b72.Td2a8ff_samples_per_second Tff7b72is Tff7b72not Tff7b72None
Tff7b72assert Tff7b72selfTff7b72.Td2a8ff_output_buffer Tff7b72is Tff7b72not Tff7b72None

T8b949e# Calculate the effective frame duration of the given PCM
T8b949e# data. Calculate it in units of 0.1ms in order to avoid
T8b949e# floating point comparisons.
Te6edf3bytes_per_sample Tff7b72= T79c0ff2
Te6edf3frame_size Tff7b72= Tb4b4b4(
Tffa657lenTb4b4b4(Te6edf3pcmTb4b4b4) T8b949e# bytes
Tff7b72/Tff7b72/ Te6edf3bytes_per_sample
Tff7b72/Tff7b72/ Tff7b72selfTff7b72.Td2a8ff_channels
Tb4b4b4)
Te6edf3frame_duration Tff7b72= Tb4b4b4(
Tb4b4b4(T79c0ff10Tff7b72*Te6edf3frame_sizeTb4b4b4)
Tff7b72/Tff7b72/ Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_samples_per_secondTff7b72/Tff7b72/T79c0ff1000Tb4b4b4)
Tb4b4b4)

T8b949e# Check that we have a valid frame size
Tff7b72if Tffa657intTb4b4b4(Te6edf3frame_durationTb4b4b4) Tff7b72not Tff7b72in Tb4b4b4[T79c0ff25Tb4b4b4, T79c0ff50Tb4b4b4, T79c0ff100Tb4b4b4, T79c0ff200Tb4b4b4, T79c0ff400Tb4b4b4, T79c0ff600Tb4b4b4]Tb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffThe effective frame duration (Tffd700{:.1f}Ta5d6ff ms) Ta5d6ff"
Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3frame_durationTff7b72/T79c0ff10Tb4b4b4)Tff7b72+
Ta5d6ff"Ta5d6ffwas not one of the acceptable values.Ta5d6ff"
Tb4b4b4)

T8b949e# Create a ctypes object sharing the memory of the PCM data
Te6edf3PcmCtypes Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffc_ubyte Tff7b72* Tffa657lenTb4b4b4(Te6edf3pcmTb4b4b4)
Tff7b72tryTb4b4b4:
T8b949e# Attempt to share the PCM memory
T8b949e# Unfortunately, as at 2020-09-27, the type hinting for
T8b949e# read-only and writeable buffer protocols was a
T8b949e# work-in-progress. The following only works for writable
T8b949e# cases, but the method's parameters include a read-only
T8b949e# possibility (bytes), thus we ignore mypy's error.
Te6edf3pcm_ctypes Tff7b72= Te6edf3PcmCtypesTff7b72.Td2a8fffrom_bufferTb4b4b4(Te6edf3pcmTb4b4b4) T8b949e# type: ignore[arg-type]
Tff7b72except Tf85149TypeErrorTb4b4b4:
T8b949e# The data must be copied if it's not writeable
Te6edf3pcm_ctypes Tff7b72= Te6edf3PcmCtypesTff7b72.Td2a8fffrom_buffer_copyTb4b4b4(Te6edf3pcmTb4b4b4)

T8b949e# Create a pointer to the PCM data
Te6edf3pcm_ptr Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffcastTb4b4b4(
Te6edf3pcm_ctypesTb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffPOINTERTb4b4b4(Te6edf3opusTff7b72.Td2a8ffopus_int16Tb4b4b4)
Tb4b4b4)

T8b949e# Create an int giving the frame size per channel
Te6edf3frame_size_int Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffc_intTb4b4b4(Te6edf3frame_sizeTb4b4b4)

T8b949e# Encode PCM
Te6edf3result Tff7b72= Te6edf3opusTff7b72.Td2a8ffopus_encodeTb4b4b4(
Tff7b72selfTff7b72.Td2a8ff_encoderTb4b4b4,
Te6edf3pcm_ptrTb4b4b4,
Te6edf3frame_size_intTb4b4b4,
Tff7b72selfTff7b72.Td2a8ff_output_buffer_ptrTb4b4b4,
Tff7b72selfTff7b72.Td2a8ff_max_bytes_per_frame
Tb4b4b4)

T8b949e# Check for any errors
Tff7b72if Te6edf3result Tff7b72< T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffAn error occurred while encoding to Opus format: Ta5d6ff"Tff7b72+
Te6edf3opusTff7b72.Td2a8ffopus_strerrorTb4b4b4(Te6edf3resultTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutfTa5d6ff"Tb4b4b4)
Tb4b4b4)

T8b949e# Get memoryview of buffer so that the slice operation doesn't
T8b949e# copy the data.
T8b949e#
T8b949e# Unfortunately, as at 2020-09-27, the type hints for
T8b949e# memoryview do not include ctype arrays. This is because
T8b949e# there is no currently accepted manner to label a class as
T8b949e# supporting the buffer protocol. However, it's clearly a
T8b949e# work in progress. For more information, see:
T8b949e# * https://bugs.python.org/issue27501
T8b949e# * https://github.com/python/typing/issues/593
T8b949e# * https://github.com/python/typeshed/pull/4232
Te6edf3mv Tff7b72= Tffa657memoryviewTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_output_bufferTb4b4b4) T8b949e# type: ignore
T8b949e# Cast the memoryview to char
Te6edf3mv Tff7b72= Te6edf3mvTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff'Ta5d6ffcTa5d6ff'Tb4b4b4)

T8b949e# Slice just the valid data from the memoryview
Te6edf3valid_data_as_bytes Tff7b72= Te6edf3mvTb4b4b4[Tb4b4b4:Te6edf3resultTb4b4b4]
T8b949e# DEBUG
T8b949e# Convert memoryview back to ctypes instance
Te6edf3Buffer Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffc_ubyte Tff7b72* Tffa657lenTb4b4b4(Te6edf3valid_data_as_bytesTb4b4b4)
Te6edf3buf Tff7b72= Te6edf3BufferTff7b72.Td2a8fffrom_bufferTb4b4b4( Te6edf3valid_data_as_bytes Tb4b4b4)
T8b949e# Convert PCM back to pointer and dump 4,000-byte buffer
Te6edf3ptr Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffcastTb4b4b4(
Te6edf3bufTb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffPOINTERTb4b4b4(Te6edf3ctypesTff7b72.Td2a8ffc_ubyteTb4b4b4)
Tb4b4b4)
Tff7b72return Te6edf3valid_data_as_bytes

Tff7b72def Td2a8ffget_algorithmic_delayTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Gets the total samples of delay added by the entire codec.

This can be queried by the encoder and then the provided
number of samples can be skipped on from the start of the
decoder's output to provide time aligned input and
output. From the perspective of a decoding application the
real data begins this many samples late.

The decoder contribution to this delay is identical for all
decoders, but the encoder portion of the delay may vary from
implementation to implementation, version to version, or even
depend on the encoder's initial configuration. Applications
needing delay compensation should call this method rather than
hard-coding a value.

"""
T8b949e# If we haven't already created an encoder, do so now
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_encoder Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_encoder Tff7b72= Tff7b72selfTff7b72.Td2a8ff_create_encoderTb4b4b4(Tb4b4b4)
T8b949e# Obtain the algorithmic delay of the Opus encoder. See
T8b949e# https://tools.ietf.org/html/rfc7845#page-27
Te6edf3delay Tff7b72= Te6edf3opusTff7b72.Td2a8ffopus_int32Tb4b4b4(Tb4b4b4)

Te6edf3result Tff7b72= Te6edf3opusTff7b72.Td2a8ffopus_encoder_ctlTb4b4b4(
Tff7b72selfTff7b72.Td2a8ff_encoderTb4b4b4,
Te6edf3opusTff7b72.Td2a8ffOPUS_GET_LOOKAHEAD_REQUESTTb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffpointerTb4b4b4(Te6edf3delayTb4b4b4)
Tb4b4b4)
Tff7b72if Te6edf3result Tff7b72!= Te6edf3opusTff7b72.Td2a8ffOPUS_OKTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffFailed to obtain the algorithmic delay of Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffthe Opus encoder: Ta5d6ff"Tff7b72+
Te6edf3opusTff7b72.Td2a8ffopus_strerrorTb4b4b4(Te6edf3resultTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutfTa5d6ff"Tb4b4b4)
Tb4b4b4)
Te6edf3delay_samples Tff7b72= Te6edf3delayTff7b72.Td2a8ffvalue
Tff7b72return Te6edf3delay_samples

T8b949e#
T8b949e# Internal methods
T8b949e#

Tff7b72def Td2a8ff_create_encoderTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Te6edf3ctypesTff7b72.Td2a8ffpointerTb4b4b4:
T8b949e# To create an encoder, we must first allocate resources for it.
T8b949e# We want Python to be responsible for the memory deallocation,
T8b949e# and thus Python must be responsible for the initial memory
T8b949e# allocation.

T8b949e# Check that the application has been defined
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_application Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffThe application was not specified before Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffattempting to create an Opus encoder. Perhaps Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffencode() was called before set_application()?Ta5d6ff"
Tb4b4b4)
Te6edf3application Tff7b72= Tff7b72selfTff7b72.Td2a8ff_application

T8b949e# Check that the sampling frequency has been defined
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_samples_per_second Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffThe sampling frequency was not specified before Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffattempting to create an Opus encoder. Perhaps Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffencode() was called before set_sampling_frequency()?Ta5d6ff"
Tb4b4b4)

T8b949e# The frequency must be passed in as a 32-bit int
Te6edf3samples_per_second Tff7b72= Te6edf3opusTff7b72.Td2a8ffopus_int32Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_samples_per_secondTb4b4b4)

T8b949e# Check that the number of channels has been defined
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_channels Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffThe number of channels were not specified before Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffattempting to create an Opus encoder. Perhaps Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffencode() was called before set_channels()?Ta5d6ff"
Tb4b4b4)
Te6edf3channels Tff7b72= Tff7b72selfTff7b72.Td2a8ff_channels

T8b949e# Obtain the number of bytes of memory required for the encoder
Te6edf3size Tff7b72= Te6edf3opusTff7b72.Td2a8ffopus_encoder_get_sizeTb4b4b4(Te6edf3channelsTb4b4b4)Tb4b4b4;

T8b949e# Allocate the required memory for the encoder
Te6edf3memory Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffcreate_string_bufferTb4b4b4(Te6edf3sizeTb4b4b4)

T8b949e# Cast the newly-allocated memory as a pointer to an encoder. We
T8b949e# could also have used opus.oe_p as the pointer type, but writing
T8b949e# it out in full may be clearer.
Te6edf3encoder Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffcastTb4b4b4(Te6edf3memoryTb4b4b4, Te6edf3ctypesTff7b72.Td2a8ffPOINTERTb4b4b4(Te6edf3opusTff7b72.Td2a8ffOpusEncoderTb4b4b4)Tb4b4b4)

T8b949e# Initialise the encoder
Te6edf3error Tff7b72= Te6edf3opusTff7b72.Td2a8ffopus_encoder_initTb4b4b4(
Te6edf3encoderTb4b4b4,
Te6edf3samples_per_secondTb4b4b4,
Te6edf3channelsTb4b4b4,
Te6edf3application
Tb4b4b4)

T8b949e# Check that there hasn't been an error when initialising the
T8b949e# encoder
Tff7b72if Te6edf3error Tff7b72!= Te6edf3opusTff7b72.Td2a8ffOPUS_OKTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffAn error occurred while creating the encoder: Ta5d6ff"Tff7b72+
Te6edf3opusTff7b72.Td2a8ffopus_strerrorTb4b4b4(Te6edf3errorTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutfTa5d6ff"Tb4b4b4)
Tb4b4b4)

T8b949e# Return our newly-created encoder
Tff7b72return Te6edf3encoder


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────